package com.farmlei.facereg.modules.face.utils;

import com.farmlei.facereg.common.utils.PropertiesUtils;
import com.farmlei.facereg.modules.face.*;
import com.sun.jna.Memory;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.PointerByReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 虹软人脸识别SDK相关工具类
 */
public final class ArcsoftUtil {
    
    public static final String ARCSORT_APPID = PropertiesUtils.getConfig().getString("arcsoft_appid");
    public static final String ARCSORT_FD_SDKKEY = PropertiesUtils.getConfig().getString("arcsoft_fd_sdkkey");
    public static final String ARCSORT_FR_SDKKEY = PropertiesUtils.getConfig().getString("arcsoft_fr_sdkkey");
    
    public static final int FD_WORKBUF_SIZE = 20 * 1024 * 1024;
    public static final int FR_WORKBUF_SIZE = 40 * 1024 * 1024;
    public static final int MAX_FACE_NUM = 50;
    public static final boolean bUseRAWFile = false;
    public static final boolean bUseBGRToEngine = true;
    private static final Logger logger = LoggerFactory.getLogger(ArcsoftUtil.class);
    private static Pointer hFDEngine;
    private static Pointer hFREngine;
    private static Pointer pFDWorkMem;
    private static Pointer pFRWorkMem;

    /**
     * 初始化引擎
     * @return
     */
    public static boolean init(){
        // init Engine
        logger.info("初始化人脸引擎");
        pFDWorkMem = CLibrary.INSTANCE.malloc(FD_WORKBUF_SIZE);
        pFRWorkMem = CLibrary.INSTANCE.malloc(FR_WORKBUF_SIZE);

        PointerByReference phFDEngine = new PointerByReference();
        NativeLong ret = AFD_FSDKLibrary.INSTANCE.AFD_FSDK_InitialFaceEngine(ARCSORT_APPID, ARCSORT_FD_SDKKEY, pFDWorkMem, FD_WORKBUF_SIZE, phFDEngine, _AFD_FSDK_OrientPriority.AFD_FSDK_OPF_0_HIGHER_EXT, 32, MAX_FACE_NUM);//��ʼ������
        if (ret.longValue() != 0) {
            CLibrary.INSTANCE.free(pFDWorkMem);
            CLibrary.INSTANCE.free(pFRWorkMem);
            logger.error("初始化人脸检测组件失败，错误编码:" + ret.longValue());
            return false;

        }

        // print FDEngine version
        hFDEngine = phFDEngine.getValue();
        //AFD_FSDK_Version versionFD = AFD_FSDKLibrary.INSTANCE.AFD_FSDK_GetVersion(hFDEngine);
        PointerByReference phFREngine = new PointerByReference();
        ret = AFR_FSDKLibrary.INSTANCE.AFR_FSDK_InitialEngine(ARCSORT_APPID, ARCSORT_FR_SDKKEY, pFRWorkMem, FR_WORKBUF_SIZE, phFREngine);
        if (ret.longValue() != 0) {
            AFD_FSDKLibrary.INSTANCE.AFD_FSDK_UninitialFaceEngine(hFDEngine);
            CLibrary.INSTANCE.free(pFDWorkMem);
            CLibrary.INSTANCE.free(pFRWorkMem);
            logger.error("初始化人脸识别组件失败，错误编码:" + ret.longValue());
            return false;
        }

        // print FREngine version
        hFREngine = phFREngine.getValue();
        //AFR_FSDK_Version versionFR = AFR_FSDKLibrary.INSTANCE.AFR_FSDK_GetVersion(hFREngine);
        return true;
    }

    /**
     * 释放引擎资源
     */
    public static void free(){
        logger.info("释放引擎资源");
        if (hFDEngine != null) {
            AFD_FSDKLibrary.INSTANCE.AFD_FSDK_UninitialFaceEngine(hFDEngine);
        }
        if (hFREngine != null) {
            AFR_FSDKLibrary.INSTANCE.AFR_FSDK_UninitialEngine(hFREngine);
        }
        if (pFDWorkMem != null) {
            CLibrary.INSTANCE.free(pFDWorkMem);
        }
        if (pFRWorkMem != null) {
            CLibrary.INSTANCE.free(pFRWorkMem);
        }
    }

    /**
     * 根据图片获取特征
     * @param path 图片路径
     */
    public static ASVLOFFSCREEN changePic(String path) throws Exception {
        System.out.println("图片地址"+path);
        String[] msg = path.split("\\.");
        //System.out.println(msg[1]);
        if (msg[1].equals("YUV") || msg[1].equals("yuv")) {
            int yuv_widthA = 640;
            int yuv_heightA = 480;
            int yuv_formatA = ASVL_COLOR_FORMAT.ASVL_PAF_I420;
            return loadRAWImage(path, yuv_widthA, yuv_heightA, yuv_formatA);
        }else{
            return loadImage(path);
        }
    }
    /**
     * 根据图片获取特征
     * @param img 缓存图片文件
     */
    public static ASVLOFFSCREEN changePic(BufferedImage img) throws Exception {
        return loadImage(img);
    }

    /**
     * 获取图片里的人脸特征，如果图片里有多个人脸，只返回第一个人脸特征
     * @param imagePath 图片路径
     * @return 人脸特征
     * @throws Exception 抛出未检测到人脸异常
     */
    public static AFR_FSDK_FACEMODEL getFaceModel(String imagePath) throws Exception {
        ASVLOFFSCREEN inputImg = loadImage(imagePath);
        FaceInfo[] faceInfos = doFaceDetection(inputImg);
        if (faceInfos.length < 1) {
            throw new Exception("未检测到人脸");
        }
        AFR_FSDK_FACEMODEL faceFeature = extractFRFeature(inputImg, faceInfos[0]);
        if (faceFeature == null) {
            logger.warn("获取人脸特征失败");
        }
        return faceFeature;
    }

    /**
     * 获取图片里的人脸特征，如果图片里有多个人脸，只返回第一个人脸特征
     * @param inputImg 图片
     * @return 人脸特征
     * @throws Exception 抛出未检测到人脸异常
     */
    public static AFR_FSDK_FACEMODEL getFaceModel(ASVLOFFSCREEN inputImg) throws Exception {
        FaceInfo[] faceInfosA = doFaceDetection(inputImg);
        if (faceInfosA.length < 1) {
            System.out.println("no face in Image");
            return null;
        }
        AFR_FSDK_FACEMODEL faceFeature = extractFRFeature( inputImg, faceInfosA[0]);
        try {
            return faceFeature.deepCopy();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取RAW图像里的人脸特征，如果图片里有多个人脸，只返回第一个人脸特征
     * @param imagePath 图片路径
     * @return 人脸特征
     * @throws Exception 抛出未检测到人脸异常
     */
    public static AFR_FSDK_FACEMODEL getRAWImageFaceModel(String imagePath) throws Exception {
        ASVLOFFSCREEN inputImg = loadRAWImage(imagePath, 640, 480, ASVL_COLOR_FORMAT.ASVL_PAF_I420);
        FaceInfo[] faceInfos = doFaceDetection(inputImg);
        if (faceInfos.length < 1) {
            logger.warn("未检测到人脸");
        }
        AFR_FSDK_FACEMODEL faceFeature = extractFRFeature(inputImg, faceInfos[0]);
        if (faceFeature == null) {
            logger.warn("获取人脸特征失败");
        }
        return faceFeature;
    }

    /**
     * 人脸探测
     * @param inputImg 图片来源
     * @return 人脸信息列表
     */
    public synchronized static FaceInfo[] doFaceDetection(ASVLOFFSCREEN inputImg) throws Exception {
            FaceInfo[] faceInfo = new FaceInfo[0];

            PointerByReference ppFaceRes = new PointerByReference();
            NativeLong ret = AFD_FSDKLibrary.INSTANCE.AFD_FSDK_StillImageFaceDetection(hFDEngine, inputImg, ppFaceRes);
            if (ret.longValue() != 0) {
                throw new Exception("人脸探测失败，错误编码：" + ret.longValue());
            }

            AFD_FSDK_FACERES faceRes = new AFD_FSDK_FACERES(ppFaceRes.getValue());
            if (faceRes.nFace > 0) {
                faceInfo = new FaceInfo[faceRes.nFace];
                for (int i = 0; i < faceRes.nFace; i++) {
                    MRECT rect = new MRECT(new Pointer(Pointer.nativeValue(faceRes.rcFace.getPointer()) + faceRes.rcFace.size() * i));
                    int orient = faceRes.lfaceOrient.getPointer().getInt(i * 4);
                    faceInfo[i] = new FaceInfo();
                    faceInfo[i].left = rect.left;
                    faceInfo[i].top = rect.top;
                    faceInfo[i].right = rect.right;
                    faceInfo[i].bottom = rect.bottom;
                    faceInfo[i].orient = orient;
                }
            }
            return faceInfo;
    }

    /**
     * 提取人脸识别特征
     * @param inputImg 图片来源
     * @param faceInfo 人脸信息
     */
    public static AFR_FSDK_FACEMODEL extractFRFeature(ASVLOFFSCREEN inputImg, FaceInfo faceInfo) throws Exception {
        AFR_FSDK_FACEINPUT faceinput = new AFR_FSDK_FACEINPUT();
        faceinput.lOrient = faceInfo.orient;
        faceinput.rcFace.left = faceInfo.left;
        faceinput.rcFace.top = faceInfo.top;
        faceinput.rcFace.right = faceInfo.right;
        faceinput.rcFace.bottom = faceInfo.bottom;

        AFR_FSDK_FACEMODEL faceFeature = new AFR_FSDK_FACEMODEL();
        NativeLong ret = AFR_FSDKLibrary.INSTANCE.AFR_FSDK_ExtractFRFeature(hFREngine, inputImg, faceinput, faceFeature);
        if (ret.longValue() != 0) {
            throw new Exception("提取人脸特征失败，错误编码：" + ret.longValue());
        }
        return faceFeature.deepCopy();
    }


    /**
     * 人脸相似度对比
     * @param path1 图片A
     * @param path2 图片B
     * @return 相似度，超过0.7可认为人脸相同
     */
    public static float toCompare(String path1, String path2) throws Exception{
        // load Image Data
        ASVLOFFSCREEN inputImgA = changePic(path1);
        ASVLOFFSCREEN inputImgB = changePic(path2);
        return compareFaceSimilarity(inputImgA, inputImgB);
    }

    /**
     * 人脸相似度对比
     * @param face1 图片A
     * @param face2 图片B
     * @return 相似度，超过0.7可认为人脸相同
     */
    public static float toCompare(AFR_FSDK_FACEMODEL face1, AFR_FSDK_FACEMODEL face2){
        FloatByReference fSimilScore = new FloatByReference(0.0f);
        NativeLong ret = AFR_FSDKLibrary.INSTANCE.AFR_FSDK_FacePairMatching(hFREngine, face1, face2, fSimilScore);
//        face1.freeUnmanaged();
//        face2.freeUnmanaged();
        if (ret.longValue() != 0) {
            logger.error("人脸匹配失败，错误编码："  + ret.longValue());
            return 0.0f;
        }
        return fSimilScore.getValue();
    }

    /**
     * 人脸相似度对比
     * @param inputImgA 图片A
     * @param inputImgB 图片B
     * @return 相似度，超过0.7可认为人脸相同
     */
    public static float compareFaceSimilarity(ASVLOFFSCREEN inputImgA, ASVLOFFSCREEN inputImgB) throws Exception {
        // Do Face Detect
        FaceInfo[] faceInfosA = doFaceDetection(inputImgA);
        if (faceInfosA.length < 1) {
            logger.error("图片A里未检测到人脸");
            return 0.0f;
        }

        FaceInfo[] faceInfosB = doFaceDetection(inputImgB);
        if (faceInfosB.length < 1) {
            logger.error("图片B里未检测到人脸");
            return 0.0f;
        }

        // Extract Face Feature
        AFR_FSDK_FACEMODEL faceFeatureA = extractFRFeature(inputImgA, faceInfosA[0]);
        if (faceFeatureA == null) {
            logger.error("从图片A里提取人脸特征失败");
            return 0.0f;
        }

        AFR_FSDK_FACEMODEL faceFeatureB = extractFRFeature(inputImgB, faceInfosB[0]);
        if (faceFeatureB == null) {
            logger.error("从图片B里提取人脸特征失败");
            faceFeatureA.freeUnmanaged();
            return 0.0f;
        }

        // calc similarity between faceA and faceB
        return toCompare(faceFeatureA, faceFeatureB);
    }


    /**
     * 读取图片信息，并保存到ASVLOFFSCREEN结构体
     * @param filePath 图片路径
     * @return
     * @throws IOException
     */
    public static ASVLOFFSCREEN loadImage(String filePath) throws IOException {
        ASVLOFFSCREEN inputImg = new ASVLOFFSCREEN();
        if (bUseBGRToEngine) {
            BufferInfo bufferInfo = ImageLoader.getBGRFromFile(filePath);
            inputImg.u32PixelArrayFormat = ASVL_COLOR_FORMAT.ASVL_PAF_RGB24_B8G8R8;
            inputImg.i32Width = bufferInfo.width;
            inputImg.i32Height = bufferInfo.height;
            inputImg.pi32Pitch[0] = inputImg.i32Width * 3;
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, bufferInfo.buffer, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = Pointer.NULL;
            inputImg.ppu8Plane[2] = Pointer.NULL;
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else {
            BufferInfo bufferInfo = ImageLoader.getI420FromFile(filePath);
            inputImg.u32PixelArrayFormat = ASVL_COLOR_FORMAT.ASVL_PAF_I420;
            inputImg.i32Width = bufferInfo.width;
            inputImg.i32Height = bufferInfo.height;
            inputImg.pi32Pitch[0] = inputImg.i32Width;
            inputImg.pi32Pitch[1] = inputImg.i32Width / 2;
            inputImg.pi32Pitch[2] = inputImg.i32Width / 2;
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, bufferInfo.buffer, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = new Memory(inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[1].write(0, bufferInfo.buffer, inputImg.pi32Pitch[0] * inputImg.i32Height, inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2] = new Memory(inputImg.pi32Pitch[2] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2].write(0, bufferInfo.buffer, inputImg.pi32Pitch[0] * inputImg.i32Height + inputImg.pi32Pitch[1] * inputImg.i32Height / 2, inputImg.pi32Pitch[2] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[3] = Pointer.NULL;
        }
        inputImg.setAutoRead(false);
        return inputImg;
    }

    /**
     * 读取图片信息，并保存到ASVLOFFSCREEN结构体
     * @param img 图片对象
     * @return
     * @throws IOException
     */
    public static ASVLOFFSCREEN loadImage(BufferedImage img) {
        ASVLOFFSCREEN inputImg = new ASVLOFFSCREEN();

        if (bUseBGRToEngine) {
            BufferInfo bufferInfo = ImageLoader.getBGRFromFile(img);
            inputImg.u32PixelArrayFormat = ASVL_COLOR_FORMAT.ASVL_PAF_RGB24_B8G8R8;
            inputImg.i32Width = bufferInfo.width;
            inputImg.i32Height = bufferInfo.height;
            inputImg.pi32Pitch[0] = inputImg.i32Width * 3;
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, bufferInfo.buffer, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = Pointer.NULL;
            inputImg.ppu8Plane[2] = Pointer.NULL;
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else {
            BufferInfo bufferInfo = ImageLoader.getI420FromFile(img);
            inputImg.u32PixelArrayFormat = ASVL_COLOR_FORMAT.ASVL_PAF_I420;
            inputImg.i32Width = bufferInfo.width;
            inputImg.i32Height = bufferInfo.height;
            inputImg.pi32Pitch[0] = inputImg.i32Width;
            inputImg.pi32Pitch[1] = inputImg.i32Width / 2;
            inputImg.pi32Pitch[2] = inputImg.i32Width / 2;
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, bufferInfo.buffer, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = new Memory(inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[1].write(0, bufferInfo.buffer, inputImg.pi32Pitch[0] * inputImg.i32Height, inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2] = new Memory(inputImg.pi32Pitch[2] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2].write(0, bufferInfo.buffer, inputImg.pi32Pitch[0] * inputImg.i32Height + inputImg.pi32Pitch[1] * inputImg.i32Height / 2, inputImg.pi32Pitch[2] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[3] = Pointer.NULL;
        }

        inputImg.setAutoRead(false);
        return inputImg;
    }

    /**
     * 读取静态图片信息，并保存到ASVLOFFSCREEN结构体
     * @param yuv_filePath 图片地址
     * @param yuv_width 宽
     * @param yuv_height 高
     * @param yuv_format 格式
     * @return
     * @throws Exception
     */
    public static ASVLOFFSCREEN loadRAWImage(String yuv_filePath, int yuv_width, int yuv_height, int yuv_format) throws Exception {
        int yuv_rawdata_size = 0;
        ASVLOFFSCREEN inputImg = new ASVLOFFSCREEN();
        inputImg.u32PixelArrayFormat = yuv_format;
        inputImg.i32Width = yuv_width;
        inputImg.i32Height = yuv_height;
        if (ASVL_COLOR_FORMAT.ASVL_PAF_I420 == inputImg.u32PixelArrayFormat) {
            inputImg.pi32Pitch[0] = inputImg.i32Width;
            inputImg.pi32Pitch[1] = inputImg.i32Width / 2;
            inputImg.pi32Pitch[2] = inputImg.i32Width / 2;
            yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3 / 2;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_NV12 == inputImg.u32PixelArrayFormat) {
            inputImg.pi32Pitch[0] = inputImg.i32Width;
            inputImg.pi32Pitch[1] = inputImg.i32Width;
            yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3 / 2;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_NV21 == inputImg.u32PixelArrayFormat) {
            inputImg.pi32Pitch[0] = inputImg.i32Width;
            inputImg.pi32Pitch[1] = inputImg.i32Width;
            yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3 / 2;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_YUYV == inputImg.u32PixelArrayFormat) {
            inputImg.pi32Pitch[0] = inputImg.i32Width * 2;
            yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 2;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_RGB24_B8G8R8 == inputImg.u32PixelArrayFormat) {
            inputImg.pi32Pitch[0] = inputImg.i32Width * 3;
            yuv_rawdata_size = inputImg.i32Width * inputImg.i32Height * 3;
        } else {
            throw new Exception("不支持的文件格式");
        }

        // load YUV Image Data from File
        byte[] imagedata = new byte[yuv_rawdata_size];
        File f = new File(yuv_filePath);
        try(InputStream ios = new FileInputStream(f);){
            ios.read(imagedata,0,yuv_rawdata_size);
        }
        if (ASVL_COLOR_FORMAT.ASVL_PAF_I420 == inputImg.u32PixelArrayFormat) {
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, imagedata, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = new Memory(inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[1].write(0, imagedata, inputImg.pi32Pitch[0] * inputImg.i32Height, inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2] = new Memory(inputImg.pi32Pitch[2] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2].write(0, imagedata, inputImg.pi32Pitch[0] * inputImg.i32Height + inputImg.pi32Pitch[1] * inputImg.i32Height / 2, inputImg.pi32Pitch[2] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_NV12 == inputImg.u32PixelArrayFormat) {
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, imagedata, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = new Memory(inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[1].write(0, imagedata, inputImg.pi32Pitch[0] * inputImg.i32Height, inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2] = Pointer.NULL;
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_NV21 == inputImg.u32PixelArrayFormat) {
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, imagedata, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = new Memory(inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[1].write(0, imagedata, inputImg.pi32Pitch[0] * inputImg.i32Height, inputImg.pi32Pitch[1] * inputImg.i32Height / 2);
            inputImg.ppu8Plane[2] = Pointer.NULL;
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_YUYV == inputImg.u32PixelArrayFormat) {
            inputImg.ppu8Plane[0] = new Memory(inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[0].write(0, imagedata, 0, inputImg.pi32Pitch[0] * inputImg.i32Height);
            inputImg.ppu8Plane[1] = Pointer.NULL;
            inputImg.ppu8Plane[2] = Pointer.NULL;
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else if (ASVL_COLOR_FORMAT.ASVL_PAF_RGB24_B8G8R8 == inputImg.u32PixelArrayFormat) {
            inputImg.ppu8Plane[0] = new Memory(imagedata.length);
            inputImg.ppu8Plane[0].write(0, imagedata, 0, imagedata.length);
            inputImg.ppu8Plane[1] = Pointer.NULL;
            inputImg.ppu8Plane[2] = Pointer.NULL;
            inputImg.ppu8Plane[3] = Pointer.NULL;
        } else {
            throw new Exception("不支持的文件格式");
        }
        inputImg.setAutoRead(false);
        return inputImg;
    }

    public static void main(String[] args) throws Exception {
        // load Image Data
        String filePathA = "d:/face_test/1.jpg";
        String filePathB = "d:/face_test/2.jpg";
        init();

        ASVLOFFSCREEN inputImgA = loadImage(filePathA);
        ASVLOFFSCREEN inputImgB = loadImage(filePathB);

        System.out.println(compareFaceSimilarity(inputImgA, inputImgB));

        free();
    }
}
